let assets = null;

if (CC_EDITOR) {
    window["Editor"].assetdb.queryAssets('db://assets/**\/*', 'prefab', function (err, results) {
        assets = results;
    });

    let prop = cc._decorator.property;
    cc._decorator.property = function (ctorProtoOrOptions) {
        if (ctorProtoOrOptions) {
            let func = prop(...arguments);
            return function (target, propertyKey) {
                func(...arguments);
                if (target.constructor._members) {
                    let type = ctorProtoOrOptions.type || ctorProtoOrOptions;
                    if (cc.js.isChildClassOf(type, cc.Node) || cc.js.isChildClassOf(type, cc.Component)) {
                        target.constructor._members[propertyKey] = type;
                    } else if (cc.js.isChildClassOf(type, cc.Prefab)) {
                        target.constructor._assets.push({ name: propertyKey, type })
                    } else if (Array.isArray(type)) {
                        target.constructor._arrType[propertyKey] = type;
                    }
                }
            }
        }
    }
}

let ccclass = cc._decorator.ccclass;
window["ccclass"] = ccclass;
let property = cc._decorator.property;
window["property"] = property;

/**弹窗相关组件 */
@ccclass
class Dialog<T> extends cc.Component {

    @property
    private get _arr() {
        for (let key in Dialog._arrType) {
            if (this[key] && Array.isArray(this[key]) && this[key].length > 0 && this[key][0]) {
                Dialog._arrType[key] = [];
                for (let i = 0; i < this[key].length; i++) {
                    if (this[key][i] && cc.isValid(this[key][i])) {
                        Dialog._arrType[key][i] = this[key][i];
                    }
                }
            }
        }
        return 0;
    }

    private static _members = {};
    private static _assets = [];
    private static _arrType = {};
    private _isReference: Map<string, boolean> = new Map();
    /**当前设置的数据 */
    protected data: T = null;

    /**绑定节点或组件 */
    private _bindProperty(node: cc.Node) {
        let type = Dialog._members[node.name];
        if (type) {
            if (this._isReference.get(node.name)) {
                cc.warn("有同名属性被引用!", node.name);
            } else {
                this._isReference.set(node.name, true);
                //节点类型
                if (cc.js.isChildClassOf(type, cc.Node)) {
                    this[node.name] = node;
                } else {
                    //组件类型
                    this[node.name] = node.getComponent(type);
                }
            }
        }
        node.children.forEach(childNode => this._bindProperty(childNode));
    }

    /**绑定预制 */
    private _bindAssets() {
        Dialog._assets.forEach((asset) => {
            let obj = assets.find((item) => {
                return item.url.endsWith(`${asset.name}.prefab`);
            });
            if (obj) {
                cc.loader.load({ type: 'uuid', uuid: obj.uuid }, (err, prefab) => {
                    this[asset.name] = prefab;
                });
            }
        });
    }


    /**数组类型不变 */
    private _arrKeep() {
        for (let key of Object.keys(Dialog._arrType)) {
            let value = Dialog._arrType[key];
            for (let i = 0; i < value.length; i++) {
                if (value[i]) {
                    this[key][i] = value[i];
                }
            }
        }
    }

    /**响应编辑器Reset按钮 */
    protected resetInEditor() {
        this._isReference.clear();
        this._bindProperty(this.node);
        this._bindAssets();
        this._arrKeep();
    }

    /**弹窗打开时候对应的回调函数 */
    onOpen() {

    }

    /**弹窗关闭时候对应的回调函数 */
    onClose() {

    }

    /**点击close节点，关闭弹窗的响应函数 */
    protected clickClose() {
        GDialog.close(this.node);
    }

    /**设置数据来改变弹窗ui显示的函数 */
    protected setData(data: T, ...para: any[]) {
        this.data = data;
        //更新界面上跟data的key同名的label和sprite
        for (let key of Object.keys(data)) {
            let value = data[key];
            if (this[key]) {
                if (this[key] instanceof cc.Label) {
                    this[key].string = value;
                } else if (this[key] instanceof cc.Sprite) {
                    if (value.indexOf("http") > -1) {//远程加载
                        cc.loader.load({ type: "png", url: value }, (err, texture) => {
                            if (err) {
                                console.error(`${value}加载错误`, err.message || err);
                            } else {
                                this[key].spriteFrame = new cc.SpriteFrame(texture);
                            }
                        });
                    } else {//本地加载
                        cc.loader.loadRes(value, cc.SpriteFrame, (err, sf) => {
                            if (err) {
                                console.error(`${value}加载错误`, err.message || err);
                            } else {
                                this[key].spriteFrame = sf;
                            }
                        });
                    }
                }
            }
        }
    }

    /**默认销毁的时候移除所有的事件监听 */
    protected onDestroy() {
        if (GEvent) {
            GEvent.offAll(this);
        }
    }

}

window["Dialog"] = Dialog;

// 1.打开关闭的回调函数 1 2
// 2.自动绑定同名节点，组件和预制，重置也只改变 节点，组件和预制，数组以及其他资源(sf)不改变
// 3.onDestroy 自动移除GEvent 1 2
// 4.setData 自动更新界面上跟data的key同名的label和sprite 1 2
// 5.clickClose 点击close节点，自动关闭当前界面 1 2

// 涉及到的组件为：
// 1.AutoComponent 更名为 Dialog 并扩展
// 2.ScrollList 滚动列表
// 3.GDialog 配合 Dialog